package anc.tankshooter.network;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import anc.server.tankshooter.models.Account;

/**
 * Đối tượng này là client trực tiếp giao tiếp với Server 
 * Nó luôn luôn lắng nghe và nhận tất cả các gói tin từ Server gửi về
 * Khi muốn xử lý thông tin gửi về thì đăng kí lớp {@link IPacketReceiver}
 * để bắt xử lý gói tin nhận đc
 * @author tauitdnmd
 *
 */
public class GameClient implements Runnable {
	
	public static final String SERVER_IP ="10.0.2.2"; //"192.168.1.106";
	public static final int SERVER_PORT = 2116;
	
	private boolean mIsLogin,mIsRunning;
	private Thread mThread;
	private Socket mSocket;
	private DataInputStream mReader;
	private DataOutputStream mWriter;
	
	private IPacketReceiver mPacketReceiver;
	private Account mLoginAccount;
	
	public GameClient() {
		
	}
	
	public void startClient(){
		if(!isRunning()) {
			mIsRunning = true;
			mThread = new Thread(this);
			mThread.start();
		}
	}
	public void stopClient(){
		mIsRunning = false;
		try {
			mWriter.close();
			mReader.close();
			mSocket.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private boolean onCreateConnection(){
		boolean isConneted = false;
		try {
			mSocket = new Socket(SERVER_IP,SERVER_PORT);
			mReader = new DataInputStream(mSocket.getInputStream());
			mWriter = new DataOutputStream(mSocket.getOutputStream());
			isConneted = true;
			
		} catch (IOException e) {
			if(mPacketReceiver!=null)
				mPacketReceiver.onDisconnected();
		}
		return isConneted ;
	}
	@Override
	public void run() {
		int command = 0;
		int dataLenght= 0;
		byte[] buffer = null;
		
		while(mIsRunning){
			
			if(onCreateConnection()){
				if(mPacketReceiver!=null)
					mPacketReceiver.onConnected();
				while(mIsRunning && mSocket.isConnected()){
					try{
						command = mReader.readInt();
						dataLenght = mReader.readInt();
						if(dataLenght>0){
							buffer = new byte[dataLenght];
							mReader.read(buffer, 0, buffer.length);
						}
						if(mPacketReceiver!=null)
							mPacketReceiver.onReceive(command,dataLenght>0?new String(buffer):"");
					}catch(IOException ex){
						break;
					}
				}
				try{
					mWriter.close(); mWriter = null;
					mReader.close(); mReader = null;
					mSocket.close(); mSocket = null;
				}catch(Exception ex){}
			}
			if(mPacketReceiver!=null)
				mPacketReceiver.onDisconnected();
		}
	}

	public boolean sendSignUp(Account acc){
		String data = String.format("%s:%s:%s:%s", acc.getUsername(),acc.getPassword(),acc.getName(),acc.getEmail());
		return send(CommandList.CLIENT_SIGNUP, data.getBytes());
	}
	
	public boolean sendLogin(String username,String password){
		String data = String.format("%s:%s", username,password);
		return send(CommandList.CLIENT_LOGIN, data.getBytes());
	}
	
	public boolean sendLogout(){
		return send(CommandList.CLIENT_LOGOUT, null);
	}
	
	public boolean sendGetAllRoom(){
		return send(CommandList.CLIENT_ALL_ROOM, null);
	}
	
	public boolean sendJoinRoom(int room){
		return send(CommandList.CLIENT_JOIN, (room+"").getBytes());
	}
	
	public boolean sendLeaveRoom(){
		return send(CommandList.CLIENT_LEAVE_ROOM, null);
	}
	
	/**
	 * Chỉ có owner mới có quyền này
	 * @return
	 */
	public boolean sendStartGame(int map){
		return send(CommandList.CLIENT_START, (map+"").getBytes());
	}
	
	public boolean sendDisconnected(){
		return send(CommandList.CLIENT_DISCONNECTED, null);
	}
	
	public boolean send(int command,byte[] data) {
		boolean isSuccess = false;
		try{
			mWriter.writeInt(command);
			mWriter.writeInt((data==null||data.length<0)?0:data.length);
			if(data!=null&&data.length>0)
				mWriter.write(data, 0, data.length);
			mWriter.flush(); // Đẩy tất cả dữ liệu lên socket và truyền đi.
			isSuccess = true;
		}catch(Exception ex){}
		return isSuccess;
	}
	
	public IPacketReceiver getPacketReceiver() {
		return mPacketReceiver;
	}

	public void setPacketReceiver(IPacketReceiver receiver) {
		this.mPacketReceiver = receiver;
	}

	public boolean isRunning() {
		return mIsRunning;
	}
	
	public boolean isConnected(){
		return mSocket!=null&&mSocket.isConnected()&&!mSocket.isOutputShutdown() && !mSocket.isInputShutdown();
	}

	public boolean isLogin() {
		return mIsLogin && mLoginAccount!=null;
	}

	public Account getAccount() {
		return mLoginAccount;
	}

	/**
	 * Khi login thanh cong
	 * @param account
	 */
	public void setAccount(Account account) {
		this.mLoginAccount = account;
		mIsLogin = mLoginAccount!=null;
	}
}
